package io.yyxx.boot.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.yyxx.boot.business.entity.billDataEntity.BillQueryParams;
import io.yyxx.boot.business.entity.billDataEntity.BillSettlementResponse;
import io.yyxx.boot.business.entity.billDataEntity.MyModule;
import io.yyxx.boot.business.entity.billDataEntity.TrainBillData;
import io.yyxx.boot.business.mapper.TrainBillDataMapper;
import io.yyxx.boot.business.service.TrainBillDataService;
import io.yyxx.boot.util.LastSyncTimeUtil;
import io.yyxx.boot.util.TrainBillApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TrainBillDataServiceImpl extends ServiceImpl<TrainBillDataMapper, TrainBillData> implements TrainBillDataService {

    private static final int BATCH_SIZE = 1000;

    @Resource
    private TrainBillApi trainBillApi;

    @Resource
    private LastSyncTimeUtil lastSyncTimeUtil;

    @Lazy
    @Resource
    private TrainBillDataService trainBillDataService;


    /**
     * 将获取的航班数据写入数据库,如果有新数据则进行保存
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveToDatabase(BillQueryParams params, String appKey, String corpToken) {
        // 1. 获取API数据,做非空判断
        if (trainBillApi == null) {
            log.error("trainBillApi 未正确注入");
            return;
        }
        // 1. 获取API数据,做非空判断

        BillSettlementResponse response = trainBillApi.queryBillSettlement(params, appKey, corpToken);

        if (response == null) {
            log.info("火车账单API返回的响应对象为空");
            return;
        }

        MyModule module = response.getModule();
        if (module == null) {
            log.info("火车账单API返回的模块对象为空");
            return;
        }

        List<TrainBillData> trainBillData = module.getDataList();
        if (trainBillData == null || trainBillData.isEmpty()) {
            log.info("火车账单API返回的火车订单数据列表为空或无数据");
            return;
        }

        // 2. 过滤已存在数据,并存入数据库中，批量保存或更新（MyBatis-Plus 自动处理）
        List<TrainBillData> filteredBills = filterExistingBills(trainBillData);
        // 3. 批量保存新数据
        if (!filteredBills.isEmpty()) {
            // 遍历列表，为每条数据添加当前时间
            filteredBills.forEach(bill -> {
                bill.setCreateTime(LocalDateTime.now());  // 设置当前时间
                bill.setSyncState(0);                   // 设置 syncStatus = 0
            });

            //将数据批量保存
            try {
                boolean saveResult = trainBillDataService.saveBatch(filteredBills);
                if (saveResult) {
                    log.info("本次成功保存 {} 条火车账单记录", filteredBills.size());
                }
            } catch (Exception e) {
                log.error("火车账单保存失败", e);
            }
        } else {
            log.info("火车账单没有新数据需要保存到数据库");
        }
        log.info("本次火车票写入数据库中的数据" + filteredBills.toString());
    }

    /**
     * 过滤已存在的账单（根据每条账单的index）
     */
    private List<TrainBillData> filterExistingBills(List<TrainBillData> newBills) {
        // 2. 提取所有Index（去重）
        Set<String> indexs = newBills.stream()
                .map(TrainBillData::getIndex)
                .filter(Objects::nonNull) // 过滤掉null值
                .collect(Collectors.toSet());

        // 3. 如果提取的Index集合为空，直接返回所有账单
        if (indexs.isEmpty()) {
            return newBills;
        }

        // 4. 查询数据库中已存在的Index
        QueryWrapper<TrainBillData> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("`index`") // 只查询需要的字段
                .in("`index`", indexs);

        Set<String> existingTradeNos = baseMapper.selectList(queryWrapper)
                .stream()
                .map(TrainBillData::getIndex)
                .filter(Objects::nonNull) // 再次过滤null
                .collect(Collectors.toSet());

        // 5. 过滤新数据：保留Index不在数据库中的记录
        return newBills.stream()
                .filter(bill -> {
                    String tradeNo = bill.getIndex();
                    // 保留交易号为null的记录，或者不在数据库中的记录
                    return tradeNo == null || !existingTradeNos.contains(tradeNo);
                })
                .collect(Collectors.toList());
    }

    //从数据库中查询火车账单数据,
    public List<TrainBillData> selectTrainBillData() {
        QueryWrapper<TrainBillData> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("dept_date", "dept_time",
                "arr_date", "arr_time",
                "dept_station", "arr_station",
                "id",
                "sync_state",
                "project_name",
                "project_code",
                "apply_id",
                "cost_center",
                "cost_center_number",

                "fee_type_desc",
                "settle_type_desc",//结算类型
                "long_ticket_no",//票号
                "bill_record_time",//入账时间

                "train_no", "order_id",
                "department_id",
                "traveler_id",
                "settlement_fee",
                "create_time",
                "book_time"); // 指定查询的数据库字段名

        //获取最后同步时间
        LocalDateTime lastSyncTime = lastSyncTimeUtil.getLastSyncTime("train_last_sync_time");

        List<TrainBillData> trainBillData = baseMapper.selectList(queryWrapper);

        //在这里对trainBillData集合进行过滤，创建时间晚于lastSyncTime最后同步时间的账单才返回
        // 过滤数据：保留 create_time > lastSyncTime 的记录
        List<TrainBillData> filteredData = trainBillData.stream()
                .filter(data ->
                        data.getCreateTime() != null &&
                                data.getCreateTime().isAfter(lastSyncTime) &&
                                data.getSyncState() != 1  // 只处理未同步的数据
                )
                .peek(data -> data.setSyncState(1))
                .collect(Collectors.toList());
        if (!filteredData.isEmpty()) {
            //更改状态信息
            updateBatchById(filteredData);
        } else {
            log.info("没有需要从数据库同步的（火车票）账单数据");
        }
        //过滤完折后更新最后同步时间
        lastSyncTimeUtil.updateSyncTimestamp(LocalDateTime.now(), "train_last_sync_time");

        return filteredData;
    }
}
